﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;


namespace Kinect.Toolbox.Wpf
{
    public class KinectCursorEventArgs : RoutedEventArgs
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="KinectCursorEventArgs"/> class.
        /// </summary>
        /// <param name="x">The X coordinate.</param>
        /// <param name="y">The Y coordinate.</param>
        public KinectCursorEventArgs(double x, double y)
        {
            X = x;
            Y = y;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="KinectCursorEventArgs"/> class.
        /// </summary>
        /// <param name="point">The position as a Point.</param>
        public KinectCursorEventArgs(Point point)
        {
            X = point.X;
            Y = point.Y;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectCursorEventArgs"/> class.
        /// </summary>
        /// <param name="routedEvent">The routed event identifier for this instance of the <see cref="T:System.Windows.RoutedEventArgs"/> class.</param>
        public KinectCursorEventArgs(RoutedEvent routedEvent) : base(routedEvent) { }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectCursorEventArgs"/> class.
        /// </summary>
        /// <param name="routedEvent">The routed event identifier for this instance of the <see cref="T:System.Windows.RoutedEventArgs"/> class.</param>
        /// <param name="x">The X coordinate.</param>
        /// <param name="y">The Y coordinate.</param>
        /// <param name="z">The Z distance in millimeters.</param>
        public KinectCursorEventArgs(RoutedEvent routedEvent, double x, double y, double z) : base(routedEvent) { X = x; Y = y; Z = z; }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectCursorEventArgs"/> class.
        /// </summary>
        /// <param name="routedEvent">The routed event.</param>
        /// <param name="point">The position as a Point.</param>
        public KinectCursorEventArgs(RoutedEvent routedEvent, Point point) : base(routedEvent) { X = point.X; Y = point.Y; }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectCursorEventArgs"/> class.
        /// </summary>
        /// <param name="routedEvent">The routed event.</param>
        /// <param name="point">The position as a Point.</param>
        /// <param name="z">The Z distance in millimeters.</param>
        public KinectCursorEventArgs(RoutedEvent routedEvent, Point point, double z) : base(routedEvent) { X = point.X; Y = point.Y; Z = z; }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectCursorEventArgs"/> class.
        /// </summary>
        /// <param name="routedEvent">The routed event identifier for this instance of the <see cref="T:System.Windows.RoutedEventArgs"/> class.</param>
        /// <param name="source">An alternate source that will be reported when the event is handled. This pre-populates the <see cref="P:System.Windows.RoutedEventArgs.Source"/> property.</param>
        public KinectCursorEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source) { }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectCursorEventArgs"/> class.
        /// </summary>
        /// <param name="routedEvent">The routed event identifier for this instance of the <see cref="T:System.Windows.RoutedEventArgs"/> class.</param>
        /// <param name="source">An alternate source that will be reported when the event is handled. This pre-populates the <see cref="P:System.Windows.RoutedEventArgs.Source"/> property.</param>
        /// <param name="x">The X coordinate.</param>
        /// <param name="y">The Y coordinate.</param>
        /// <param name="z">The Z distance in millimeters.</param>
        public KinectCursorEventArgs(RoutedEvent routedEvent, object source, double x, double y, double z) : base(routedEvent, source) { X = x; Y = y; Z = z; }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectCursorEventArgs"/> class.
        /// </summary>
        /// <param name="routedEvent">The routed event identifier for this instance of the <see cref="T:System.Windows.RoutedEventArgs"/> class.</param>
        /// <param name="source">An alternate source that will be reported when the event is handled. This pre-populates the <see cref="P:System.Windows.RoutedEventArgs.Source"/> property.</param>
        /// <param name="point">The position as a Point.</param>
        public KinectCursorEventArgs(RoutedEvent routedEvent, object source, Point point) : base(routedEvent, source) { X = point.X; Y = point.Y; }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectCursorEventArgs"/> class.
        /// </summary>
        /// <param name="routedEvent">The routed event identifier for this instance of the <see cref="T:System.Windows.RoutedEventArgs"/> class.</param>
        /// <param name="source">An alternate source that will be reported when the event is handled. This pre-populates the <see cref="P:System.Windows.RoutedEventArgs.Source"/> property.</param>
        /// <param name="point">The position as a Point.</param>
        /// /// <param name="z">The Z distance in millimeters.</param>
        public KinectCursorEventArgs(RoutedEvent routedEvent, object source, Point point, double z) : base(routedEvent, source) { X = point.X; Y = point.Y; Z = z; }

        /// <summary>
        /// Gets or sets the X coordinate.
        /// </summary>
        /// <value>
        /// The X.
        /// </value>
        public double X { get; set; }

        /// <summary>
        /// Gets or sets the Y coordinate.
        /// </summary>
        /// <value>
        /// The Y.
        /// </value>
        public double Y { get; set; }
        /// <summary>
        /// Gets or sets the Z value in millimeters.
        /// </summary>
        /// <value>
        /// The Z.
        /// </value>
        public double Z { get; set; }
        /// <summary>
        /// Gets or sets the cursor.
        /// </summary>
        /// <value>
        /// The cursor.
        /// </value>
        public CursorAdorner Cursor { get; set; }
    }


    public delegate void KinectCursorEventHandler(object sender, KinectCursorEventArgs e);


    public static class KinectCursorInput
    {
        #region KinectCursorEnter

        /// <summary>
        /// Identifies the KinectCursorEnterEvent.
        /// </summary>
        public static readonly RoutedEvent KinectCursorEnterEvent = EventManager.RegisterRoutedEvent("KinectCursorEnter", RoutingStrategy.Bubble,
            typeof(KinectCursorEventHandler), typeof(KinectCursorInput));
        /// <summary>
        /// Adds a specified event handler for the KinectCursorEnter event.
        /// </summary>
        /// <param name="o">The object that listens to the event.</param>
        /// <param name="handler">The event handler to add.</param>
        public static void AddKinectCursorEnterHandler(DependencyObject o, KinectCursorEventHandler handler)
        {
            ((UIElement)o).AddHandler(KinectCursorEnterEvent, handler);
        }
        /// <summary>
        /// Remove the specified event handler for the KinectCursorEnter event.
        /// </summary>
        /// <param name="o">The object that listens to the event.</param>
        /// <param name="handler">The event handler to add.</param>
        public static void RemoveKinectCursorEnterHandler(DependencyObject o, KinectCursorEventHandler handler)
        {
            ((UIElement)o).RemoveHandler(KinectCursorEnterEvent, handler);
        }

        #endregion

        #region KinectCursorLeave

        /// <summary>
        /// Identifies the KinectCursorLeaveEvent.
        /// </summary>
        public static readonly RoutedEvent KinectCursorLeaveEvent = EventManager.RegisterRoutedEvent("KinectCursorLeave", RoutingStrategy.Bubble,
            typeof(KinectCursorEventHandler), typeof(KinectCursorInput));
        /// <summary>
        /// Adds a specified event handler for the KinectCursorLeave event.
        /// </summary>
        /// <param name="o">The object that listens to the event.</param>
        /// <param name="handler">The event handler to add.</param>
        public static void AddKinectCursorLeaveHandler(DependencyObject o, KinectCursorEventHandler handler)
        {
            ((UIElement)o).AddHandler(KinectCursorEnterEvent, handler);
        }
        /// <summary>
        /// Remove the specified event handler for the KinectCursorLeave event.
        /// </summary>
        /// <param name="o">The object that listens to the event.</param>
        /// <param name="handler">The event handler to add.</param>
        public static void RemoveKinectCursorLeaveHandler(DependencyObject o, KinectCursorEventHandler handler)
        {
            ((UIElement)o).RemoveHandler(KinectCursorEnterEvent, handler);
        }

        #endregion

        #region KinectCursorActivated

        /// <summary>
        /// Identifies the KinectCursorActivatedEvent.
        /// </summary>
        public static readonly RoutedEvent KinectCursorActivatedEvent = EventManager.RegisterRoutedEvent("KinectCursorActivated", RoutingStrategy.Bubble,
            typeof(RoutedEventHandler), typeof(KinectCursorInput));
        /// <summary>
        /// Adds a specified event handler for the KinectCursorActivated event.
        /// </summary>
        /// <param name="o">The object that listens to the event.</param>
        /// <param name="handler">The event handler to add.</param>
        public static void AddKinectCursorActivatedHandler(DependencyObject o, RoutedEventHandler handler)
        {
            ((UIElement)o).AddHandler(KinectCursorActivatedEvent, handler);
        }
        /// <summary>
        /// Remove the specified event handler for the KinectCursorActivated event.
        /// </summary>
        /// <param name="o">The object that listens to the event.</param>
        /// <param name="handler">The event handler to add.</param>
        public static void RemoveKinectCursorActivatedHandler(DependencyObject o, RoutedEventHandler handler)
        {
            ((UIElement)o).RemoveHandler(KinectCursorActivatedEvent, handler);
        }
        #endregion

        #region KinectCursorDeactivated
        /// <summary>
        /// Identifies the KinectCursorvctivatedEvent.
        /// </summary>
        public static readonly RoutedEvent KinectCursorDeactivatedEvent = EventManager.RegisterRoutedEvent("KinectCursorDeactivated", RoutingStrategy.Bubble,
            typeof(RoutedEventHandler), typeof(KinectCursorInput));
        /// <summary>
        /// Adds a specified event handler for the KinectCursorDeactivated event.
        /// </summary>
        /// <param name="o">The object that listens to the event.</param>
        /// <param name="handler">The event handler to add.</param>
        public static void AddKinectCursorDeactivatedHandler(DependencyObject o, RoutedEventHandler handler)
        {
            ((UIElement)o).AddHandler(KinectCursorDeactivatedEvent, handler);
        }
        /// <summary>
        /// Remove the specified event handler for the KinectCursorDeactivated event.
        /// </summary>
        /// <param name="o">The object that listens to the event.</param>
        /// <param name="handler">The event handler to add.</param>
        public static void RemoveKinectCursorDeactivatedHandler(DependencyObject o, RoutedEventHandler handler)
        {
            ((UIElement)o).RemoveHandler(KinectCursorDeactivatedEvent, handler);
        }
        #endregion

        #region KinectCursorMove

        /// <summary>
        /// Identifies the KinectCursorMoveEvent.
        /// </summary>
        public static readonly RoutedEvent KinectCursorMoveEvent = EventManager.RegisterRoutedEvent("KinectCursorMove", RoutingStrategy.Bubble,
            typeof(KinectCursorEventHandler), typeof(KinectCursorInput));
        /// <summary>
        /// Adds a specified event handler for the KinectCursorMove event.
        /// </summary>
        /// <param name="o">The object that listens to the event.</param>
        /// <param name="handler">The event handler to add.</param>
        public static void AddKinectCursorMoveHandler(DependencyObject o, KinectCursorEventHandler handler)
        {
            ((UIElement)o).AddHandler(KinectCursorMoveEvent, handler);
        }
        /// <summary>
        /// Remove the specified event handler for the KinectCursorMove event.
        /// </summary>
        /// <param name="o">The object that listens to the event.</param>
        /// <param name="handler">The event handler to add.</param>
        public static void RemoveKinectCursorMoveHandler(DependencyObject o, KinectCursorEventHandler handler)
        {
            ((UIElement)o).RemoveHandler(KinectCursorMoveEvent, handler);
        }
        #endregion

        public static readonly RoutedEvent KinectCursorLockEvent = EventManager.RegisterRoutedEvent("KinectCursorLock", RoutingStrategy.Bubble,
    typeof(KinectCursorEventHandler), typeof(KinectCursorInput));

        /// <summary>
        /// Adds the kinect cursor lock handler.
        /// </summary>
        /// <param name="o">The o.</param>
        /// <param name="handler">The handler.</param>
        public static void AddKinectCursorLockHandler(DependencyObject o, KinectCursorEventHandler handler)
        {
            ((UIElement)o).AddHandler(KinectCursorLockEvent, handler);
        }

        public static readonly RoutedEvent KinectCursorUnlockEvent = EventManager.RegisterRoutedEvent("KinectCursorUnlock", RoutingStrategy.Bubble,
    typeof(KinectCursorEventHandler), typeof(KinectCursorInput));

        /// <summary>
        /// Adds the kinect cursor unlock handler.
        /// </summary>
        /// <param name="o">The o.</param>
        /// <param name="handler">The handler.</param>
        public static void AddKinectCursorUnlockHandler(DependencyObject o, KinectCursorEventHandler handler)
        {
            ((UIElement)o).AddHandler(KinectCursorUnlockEvent, handler);
        }
    }
    public class KinectButton : Button
    {
        public static readonly RoutedEvent KinectCursorEnterEvent = KinectCursorInput.KinectCursorEnterEvent.AddOwner(typeof(KinectButton));
        public static readonly RoutedEvent KinectCursorLeaveEvent = KinectCursorInput.KinectCursorLeaveEvent.AddOwner(typeof(KinectButton));
        public static readonly RoutedEvent KinectCursorMoveEvent = KinectCursorInput.KinectCursorMoveEvent.AddOwner(typeof(KinectButton));
        public static readonly RoutedEvent KinectCursorActivatedEvent = KinectCursorInput.KinectCursorActivatedEvent.AddOwner(typeof(KinectButton));
        public static readonly RoutedEvent KinectCursorDeactivatedEvent = KinectCursorInput.KinectCursorDeactivatedEvent.AddOwner(typeof(KinectButton));


        public event KinectCursorEventHandler KinectCursorEnter
        {
            add { base.AddHandler(KinectCursorEnterEvent, value); }
            remove { base.RemoveHandler(KinectCursorEnterEvent, value); }
        }

        public event KinectCursorEventHandler KinectCursorLeave
        {
            add { base.AddHandler(KinectCursorLeaveEvent, value); }
            remove { base.RemoveHandler(KinectCursorLeaveEvent, value); }
        }

        public event KinectCursorEventHandler KinectCursorMove
        {
            add { base.AddHandler(KinectCursorMoveEvent, value); }
            remove { base.RemoveHandler(KinectCursorMoveEvent, value); }
        }

        public event RoutedEventHandler KinectCursorActivated
        {
            add { base.AddHandler(KinectCursorActivatedEvent, value); }
            remove { base.RemoveHandler(KinectCursorActivatedEvent, value); }
        }

        public event RoutedEventHandler KinectCursorDeactivated
        {
            add { base.AddHandler(KinectCursorDeactivatedEvent, value); }
            remove { base.RemoveHandler(KinectCursorDeactivatedEvent, value); }
        }

        public KinectButton()
        {
            //autogen the manager if needed
            if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
                CursorWpf.Create(Application.Current.MainWindow);


            this.KinectCursorEnter += new KinectCursorEventHandler(OnKinectCursorEnter);
            this.KinectCursorLeave += new KinectCursorEventHandler(OnKinectCursorLeave);
            this.KinectCursorMove += new KinectCursorEventHandler(OnKinectCursorMove);
            this.KinectCursorActivated += new RoutedEventHandler(OnKinectCursorActivated);
            this.KinectCursorDeactivated += new RoutedEventHandler(OnKinectCursorDeactivated);
        }

        protected virtual void OnKinectCursorEnter(object sender, KinectCursorEventArgs e)
        {
            RaiseEvent(new RoutedEventArgs(ClickEvent));
        }

        protected virtual void OnKinectCursorLeave(object sender, KinectCursorEventArgs e)
        {

        }

        protected virtual void OnKinectCursorMove(object sender, KinectCursorEventArgs e)
        {

        }
        protected virtual void OnKinectCursorActivated(object sender, RoutedEventArgs e)
        {

        }

        protected virtual void OnKinectCursorDeactivated(object sender, RoutedEventArgs e)
        {

        }

    }
}
